package bookhive.utils;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Iterator;
import java.util.TreeSet;
import java.util.Vector;

import org.jopac2.jbal.RecordInterface;
import org.jopac2.utils.Parametro;

import bookhive.datastructures.datasource.DataItem;
import bookhive.datastructures.datasource.HashItem;


import net.jxta.document.Document;
import net.jxta.document.Element;
import net.jxta.document.MimeMediaType;
import net.jxta.document.StructuredDocumentFactory;
import net.jxta.document.XMLDocument;
import net.jxta.endpoint.InputStreamMessageElement;
import net.jxta.endpoint.Message;
import net.jxta.protocol.PipeAdvertisement;

public class MessageCreator {

	private static MimeMediaType XMLMIMETYPE = new MimeMediaType("text/xml");

	private static String ENCODING = "UTF-8";

	@SuppressWarnings("unchecked")
	public static Message createDataQueryMessage(TreeSet<String> hashes,
			PipeAdvertisement responsePipeAdv) {

		Message m = createMessageWithReponsePipeAdv(responsePipeAdv);

		XMLDocument xml = (XMLDocument) StructuredDocumentFactory
				.newStructuredDocument(XMLMIMETYPE, "Request");

		Iterator<String> hashesIter = hashes.iterator();
		while (hashesIter.hasNext()) {
			String hash = hashesIter.next();
			try {
				hash = URLEncoder.encode(hash, ENCODING);
			} catch (UnsupportedEncodingException e) {
				e.printStackTrace();
			}

			Element queryEl = xml.createElement("Query");
			xml.appendChild(queryEl);

			Element queryTypeEl = xml.createElement("QueryType", "data");
			queryEl.appendChild(queryTypeEl);

			Element queryDataEl = xml.createElement("QueryData", hash);
			queryEl.appendChild(queryDataEl);
		}

		try {
			InputStreamMessageElement isme = new InputStreamMessageElement(
					"Request", XMLMIMETYPE, xml.getStream(), null);
			m.addMessageElement(isme);
		} catch (IOException e) {
			e.printStackTrace();
		}

		return m;
	}

	@SuppressWarnings("unchecked")
	public static Message createHashQueryMessage(
			TreeSet<Vector<Parametro>> attributesSet,
			PipeAdvertisement responsePipeAdv) {

		Message m = createMessageWithReponsePipeAdv(responsePipeAdv);

		XMLDocument xml = (XMLDocument) StructuredDocumentFactory
				.newStructuredDocument(XMLMIMETYPE, "Request");

		Iterator<Vector<Parametro>> attributesSetIter = attributesSet
				.iterator();
		while (attributesSetIter.hasNext()) {
			Vector<Parametro> props = attributesSetIter.next();
			String queryData = propsToString(props);
			try {
				queryData = URLEncoder.encode(queryData, ENCODING);
			} catch (UnsupportedEncodingException e) {
				e.printStackTrace();
			}

			Element queryEl = xml.createElement("Query");
			xml.appendChild(queryEl);

			Element queryTypeEl = xml.createElement("QueryType", "hash");
			queryEl.appendChild(queryTypeEl);

			Element queryDataEl = xml.createElement("QueryData", queryData);
			queryEl.appendChild(queryDataEl);
		}

		try {
			InputStreamMessageElement isme = new InputStreamMessageElement(
					"Request", XMLMIMETYPE, xml.getStream(), null);
			m.addMessageElement(isme);
		} catch (IOException e) {
			e.printStackTrace();
		}

		return m;
	}

	@SuppressWarnings("unchecked")
	public static Message createHashQueryMessage(String hashquery,
			PipeAdvertisement responsePipeAdv) {

		Message m = createMessageWithReponsePipeAdv(responsePipeAdv);

		XMLDocument xml = (XMLDocument) StructuredDocumentFactory
				.newStructuredDocument(XMLMIMETYPE, "Request");

		String queryData = hashquery;
		try {
			queryData = URLEncoder.encode(queryData, ENCODING);
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}

		Element queryEl = xml.createElement("Query");
		xml.appendChild(queryEl);

		Element queryTypeEl = xml.createElement("QueryType", "hash");
		queryEl.appendChild(queryTypeEl);

		Element queryDataEl = xml.createElement("QueryData", queryData);
		queryEl.appendChild(queryDataEl);

		try {
			InputStreamMessageElement isme = new InputStreamMessageElement(
					"Request", XMLMIMETYPE, xml.getStream(), null);
			m.addMessageElement(isme);
		} catch (IOException e) {
			e.printStackTrace();
		}

		return m;
	}

	private static Message createMessageWithReponsePipeAdv(
			PipeAdvertisement responsePipeAdv) {
		Message m = new Message();

		Document responsePipeAdvXml = responsePipeAdv.getDocument(XMLMIMETYPE);
		try {
			InputStreamMessageElement isme = new InputStreamMessageElement(
					"Requestor", XMLMIMETYPE, responsePipeAdvXml.getStream(),
					null);
			m.addMessageElement(isme);
		} catch (IOException e) {
			e.printStackTrace();
		}

		return m;
	}

	private static String propsToString(Vector<Parametro> params) {

		StringBuffer sb = new StringBuffer();

		Iterator<Parametro> paramIter = params.iterator();
		while (paramIter.hasNext()) {
			Parametro param = paramIter.next();
			sb.append(param.getChiave().toString());
			sb.append("=");
			sb.append(param.getValore().toString());
			sb.append("&");
		}

		sb = sb.deleteCharAt(sb.length() - 1);

		return sb.toString();

	}

	@SuppressWarnings("unchecked")
	public static Message createUpdateMessage(Vector<RecordInterface> ris,
			PipeAdvertisement responsePipeAdv) {

		Message m = createMessageWithReponsePipeAdv(responsePipeAdv);

		XMLDocument xml = (XMLDocument) StructuredDocumentFactory
				.newStructuredDocument(XMLMIMETYPE, "Request");

		Iterator<RecordInterface> risIterator = ris.iterator();
		while (risIterator.hasNext()) {

			RecordInterface ri = risIterator.next();
			HashItem hi = new HashItem(ri);

			Element queryEl = xml.createElement("Query");
			xml.appendChild(queryEl);

			Element queryTypeEl = xml.createElement("QueryType", "update");
			queryEl.appendChild(queryTypeEl);

			XMLDocument bsignsXml = (XMLDocument) StructuredDocumentFactory
					.newStructuredDocument(XMLMIMETYPE, "Update");
			try {
				hi.addToParentElement(bsignsXml, bsignsXml);
			} catch (UnsupportedEncodingException e) {
				e.printStackTrace();
			}
			String queryData = bsignsXml.toString().replaceAll("\n", "")
					.replaceAll("\r", "").replaceAll("\t", "").trim();

			try {
				queryData = URLEncoder.encode(queryData, ENCODING);
			} catch (UnsupportedEncodingException e) {
				e.printStackTrace();
			}

			Element queryDataEl = xml.createElement("QueryData", queryData);
			queryEl.appendChild(queryDataEl);

		}

		try {
			InputStreamMessageElement isme = new InputStreamMessageElement(
					"Request", XMLMIMETYPE, xml.getStream(), null);
			m.addMessageElement(isme);
		} catch (IOException e) {
			e.printStackTrace();
		}

		return m;
	}

	public static Message createRedundateQueryMessage(DataItem record,
			PipeAdvertisement responsePipeAdv) {

		Message m = createMessageWithReponsePipeAdv(responsePipeAdv);

		XMLDocument xml = (XMLDocument) StructuredDocumentFactory
				.newStructuredDocument(XMLMIMETYPE, "Request");

		Element queryEl = xml.createElement("Query");
		xml.appendChild(queryEl);

		Element queryTypeEl = xml.createElement("QueryType", "redundate");
		queryEl.appendChild(queryTypeEl);

		XMLDocument bsignsXml = (XMLDocument) StructuredDocumentFactory
				.newStructuredDocument(XMLMIMETYPE, "Redundate");
		try {
			record.addToParentElement(bsignsXml, bsignsXml);
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		String queryData = bsignsXml.toString().replaceAll("\n", "")
				.replaceAll("\r", "").replaceAll("\t", "").trim();

		try {
			queryData = URLEncoder.encode(queryData, ENCODING);
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}

		Element queryDataEl = xml.createElement("QueryData", queryData);
		queryEl.appendChild(queryDataEl);

		try {
			InputStreamMessageElement isme = new InputStreamMessageElement(
					"Request", XMLMIMETYPE, xml.getStream(), null);
			m.addMessageElement(isme);
		} catch (IOException e) {
			e.printStackTrace();
		}

		return m;
	}

}
